#pragma once
#include <iostream>
#include <vector>
#include <pthread.h>
#include <cstdio>
#include "Sem.hpp"
#include "LockGuard.hpp"
const static int g_num_default = 2;
template <class T>
class RingQueue
{
public:
    RingQueue(const int num = g_num_default)
        : num_(num),
          rqueue_(num),
          pro_step_(0),
          con_step_(0),
          data_sem_(0),
          size_(0),
          space_sem_(num),
          p_mutex( new pthread_mutex_t()),
          c_mutex( new pthread_mutex_t())
    {
        //logMessage(NORMAL, "RingQueue:%p",&p_mutex);
        //logMessage(NORMAL, "RingQueue:%p",&c_mutex);
    }
    ~RingQueue()
    {
    }
    void push(const T &x)
    {
        space_sem_.P(); // 申请信号量
        {
            LockGuard lockGuard(&p_mutex);
            rqueue_[pro_step_++] = x;
            size_++;
            pro_step_ %= num_;
        }
        data_sem_.V();
    }
    void pop(T *y)
    {
        data_sem_.P();
        {
            LockGuard lockGuard(&c_mutex);
            *y = rqueue_[con_step_++];
            con_step_ %= num_;
            size_ --;
        }
        space_sem_.V();
    }
    bool is_full()
    {
        return size_==num_;
    }
    bool is_empty()
    {
        return size_ == 0;
    }
    void Clear()
    {
        space_sem_.V();
        data_sem_.V();
        //rqueue_.clear();
    }

private:
    std::vector<T> rqueue_; // 模拟队列
    int num_;               // 元素个数
    int pro_step_;          // 生产下标
    int con_step_;          // 消费下标
    int size_;
    Mutex p_mutex; // 锁
    Mutex c_mutex;
    Sem data_sem_;  // 数据信号量
    Sem space_sem_; // 空间信号量
};